---
slug: /
position: 1
title: Quickstart
description: 适用于Node.js的MySQL客户端，专注于性能优化
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import { PageTitle } from '@site/src/components/PageTitle';

<PageTitle title='MySQL2 | Quickstart' />

# MySQL2

{/* <Logo className='logo' width={150} height={150} /> */}

适用于Node.js的MySQL客户端，专注于性能优化。支持SQL预处理、非UTF-8编码支持、二进制文件编码支持、压缩和SSL等等 查看更多。

[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Node.js Version][node-version-image]][node-version-url]
[![GitHub Workflow Status (with event)][ci-image]][ci-url]
[![Codecov][coverage]][coverage-url]
[![License][license-image]][license-url]

## 安装

MySQL2 可以跨平台使用，毫无疑问可以安装在 Linux、Mac OS 或 Windows 上。

<Tabs>
  <TabItem value='JavaScript' default>

```bash
npm install --save mysql2
```

  </TabItem>
  <TabItem value='TypeScript'>

```bash
npm install --save mysql2
npm install --save-dev @types/node
```

    更多关于`TypeScript`相关文档内容，请点击 [这里](/docs/documentation/typescript-examples) 查看。

  </TabItem>
</Tabs>

<hr />

### 查询数据

> 更多查询语法内容，请点击 [**简单查询**](/docs/examples/queries/simple-queries) 和 [**预处理**](/docs/examples/queries/prepared-statements)。

<Tabs>
  <TabItem value='Promise' default>

```js
// 导入模块
import mysql from 'mysql2/promise';

// 创建一个数据库连接
const connection = await mysql.createConnection({
  host: 'localhost',
  user: 'root',
  database: 'test',
});

// 简单查询
try {
  const [results, fields] = await connection.query(
    'SELECT * FROM `table` WHERE `name` = "Page" AND `age` > 45'
  );

  console.log(results); // 结果集
  console.log(fields); // 额外的元数据（如果有的话）
} catch (err) {
  console.log(err);
}

// 使用占位符
try {
  const [results] = await connection.query(
    'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
    ['Page', 45]
  );

  console.log(results);
} catch (err) {
  console.log(err);
}
```

  </TabItem>
  <TabItem value='Callback'>

```js
// 导入模块
const mysql = require('mysql2');

// 创建一个数据库连接
const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  database: 'test',
});

// 简单查询
connection.query(
  'SELECT * FROM `table` WHERE `name` = "Page" AND `age` > 45',
  function (err, results, fields) {
    console.log(results); // 结果集
    console.log(fields); // 额外的元数据（如果有的话）
  }
);

// 使用占位符
connection.query(
  'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
  ['Page', 45],
  function (err, results) {
    console.log(results);
  }
);
```

  </TabItem>
</Tabs>

<hr />

### SQL预处理的使用

使用 MySQL2，您还可以提前准备好SQL预处理语句。 使用准备好的SQL预处理语句，MySQL 不必每次都为相同的查询做准备，这会带来更好的性能。 如果您不知道为什么它们很重要，请查看这些讨论：

- [如何防止预处理语句SQL注入攻击](https://stackoverflow.com/questions/8263371/how-can-prepared-statements-protect-from-sql-injection-attacks)

MySQL2 提供了 `execute` 辅助函数，它将准备和查询语句。 您还可以使用 `prepare` / `unprepare` 方法手动准备/取消准备。

> 更多关于预处理和占位符相关内容，请点击 [**预处理**](/docs/examples/queries/prepared-statements)。

<Tabs>
  <TabItem value='Promise' default>

```js
import mysql from 'mysql2/promise';

try {
  // 创建一个数据库连接
  const connection = await mysql.createConnection({
    host: 'localhost',
    user: 'root',
    database: 'test',
  });

  // execute 将在内部调用 prepare 和 query
  const [results, fields] = await connection.execute(
    'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
    ['Rick C-137', 53]
  );

  console.log(results); // 结果集
  console.log(fields); // 额外的元数据（如果有的话）
} catch (err) {
  console.log(err);
}
```

  </TabItem>
  <TabItem value='Callback'>

```js
const mysql = require('mysql2');

// 创建一个数据库连接
const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  database: 'test',
});

// execute 将在内部调用 prepare 和 query
connection.execute(
  'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
  ['Rick C-137', 53],
  function (err, results, fields) {
    console.log(results); // 结果集
    console.log(fields); // 额外的元数据（如果有的话）
  }
);
```

  </TabItem>
</Tabs>

:::tip
如果再次执行相同的语句，他将从缓存中选取，这能有效的节省准备查询时间获得更好的性能。
:::

<hr />

### 连接池的使用 {#using-connection-pools}

连接池通过重用以前的连接来帮助减少连接到 MySQL 服务器所花费的时间，当你完成它们时让它们保持打开而不是关闭。

这改善了查询的延迟，因为您避免了建立新连接所带来的所有开销。

> 更多关于连接池等相关内容，请点击 [**创建连接池**](/docs/examples/connections/create-pool).

<Tabs>
  <TabItem value='Promise' default>

```js
import mysql from 'mysql2/promise';

// 创建连接池，设置连接池的参数
const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  database: 'test',
  waitForConnections: true,
  connectionLimit: 10,
  maxIdle: 10, // 最大空闲连接数，默认等于 `connectionLimit`
  idleTimeout: 60000, // 空闲连接超时，以毫秒为单位，默认值为 60000 ms
  queueLimit: 0,
  enableKeepAlive: true,
  keepAliveInitialDelay: 0,
});
```

  </TabItem>
  <TabItem value='Callback'>

```js
const mysql = require('mysql2');

// 创建连接池，设置连接池的参数
const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  database: 'test',
  waitForConnections: true,
  connectionLimit: 10,
  maxIdle: 10, // 最大空闲连接数，默认等于 `connectionLimit`
  idleTimeout: 60000, // 空闲连接超时，以毫秒为单位，默认值为 60000 ms
  queueLimit: 0,
  enableKeepAlive: true,
  keepAliveInitialDelay: 0,
});
```

  </TabItem>
</Tabs>

:::note
该池不会预先创建所有连接，而是根据需要创建它们，直到达到连接限制。
:::

<hr />

您可以像直接连接一样使用池（使用 `pool.query()` 和 `pool.execute()`）：

<Tabs>
  <TabItem value='Promise' default>

```js
try {
  // 关于连接池初始化，请参阅上文
  const [rows, fields] = await pool.query('SELECT `field` FROM `table`');
  // 查询解析时，连接会自动释放
} catch (err) {
  console.log(err);
}
```

  </TabItem>
  <TabItem value='Callback'>

```js
// 关于连接池初始化，请参阅上文
pool.query('SELECT `field` FROM `table`', function (err, rows, fields) {
  // 查询解析时，连接会自动释放
});
```

  </TabItem>
</Tabs>

或者，也可以手动从池中获取连接并稍后返回：

<Tabs>
  <TabItem value='Promise' default>

```js
// 关于连接池初始化，请参阅上文
const conn = await pool.getConnection();

// 对连接执行某些操作
await conn.query(/* ... */);

// 不要忘记释放连接！
pool.releaseConnection(conn);
```

  </TabItem>
  <TabItem value='Callback'>

```js
// 关于连接池初始化，请参阅上文
pool.getConnection(function (err, conn) {
  // 对连接执行某些操作
  conn.query(/* ... */);

  // 不要忘记释放连接！
  pool.releaseConnection(conn);
});
```

  </TabItem>
</Tabs>

- 此外，使用`connection`对象直接释放连接:

  ```js
  conn.release();
  ```

<hr />

### Promise封装

MySQL2 也支持 Promise API。 这与 ES7 异步等待非常有效。

```js
import mysql from 'mysql2/promise';

async function main() {
  // 创建链接
  const connection = await mysql.createConnection({
    host: 'localhost',
    user: 'root',
    database: 'test',
  });

  // 查询数据库
  const [rows, fields] = await connection.execute(
    'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
    ['Morty', 14]
  );
}
```

MySQL2 使用范围内可用的默认 `Promise` 对象。 但是你可以选择你想使用的 `Promise` 实现。

```js
// 导入模块
import mysql from 'mysql2/promise';

// 获取 promise 实现，这里我们将使用 bluebird 这个库来实现
import bluebird from 'bluebird';

// 创建连接，将 bluebird 指定为 Promise
const connection = await mysql.createConnection({
  host: 'localhost',
  user: 'root',
  database: 'test',
  Promise: bluebird,
});

// 查询数据
const [rows, fields] = await connection.execute(
  'SELECT * FROM `table` WHERE `name` = ? AND `age` > ?',
  ['Morty', 14]
);
```

MySQL2 还在 Pools 上公开了一个 `.promise()`函数，因此您可以从同一个池创建一个 promise/non-promise 连接。

```js
import mysql from 'mysql2';

async function main() {
  // 创建连接池
  const pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    database: 'test',
  });

  // now get a Promise wrapped instance of that pool
  // 现在获取一个链接池的 Promise 包装实例
  const promisePool = pool.promise();

  // 使用 Promise 查询数据库
  const [rows, fields] = await promisePool.query('SELECT 1');
}
```

MySQL2 在 Connections 上公开了一个 `.promise()`函数，以“升级”现有的 non-promise 连接以使用 Promise。

```js {11}
const mysql = require('mysql2');

// 创建连接
const conn = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  database: 'test',
});

conn
  .promise()
  .query('SELECT 1')
  .then(([rows, fields]) => {
    console.log(rows);
  })
  .catch(console.log)
  .then(() => conn.end());
```

<hr />

### 结果返回

如果你有两个相同名称的列，你可能希望以数组而不是对象的形式获取结果，为了防止冲突，这是与 [Node MySQL][node-mysql] 库的区别。

例如： `` SELECT 1 AS `foo`, 2 AS `foo` ``.

您可以在连接级别（适用于所有查询）或查询级别（仅适用于该特定查询）启用此设置。

#### 连接级别

<Tabs>
  <TabItem value='Promise' default>

```js {5}
const conn = await mysql.createConnection({
  host: 'localhost',
  database: 'test',
  user: 'root',
  rowsAsArray: true,
});
```

  </TabItem>
  <TabItem value='Callback'>

```js {5}
const conn = mysql.createConnection({
  host: 'localhost',
  database: 'test',
  user: 'root',
  rowsAsArray: true,
});
```

  </TabItem>
</Tabs>

#### 查询级别

<Tabs>
  <TabItem value='Promise' default>

```js {4}
try {
  const [results, fields] = await conn.query({
    sql: 'SELECT 1 AS `foo`, 2 AS `foo`',
    rowsAsArray: true,
  });

  console.log(results); // 返回数组而不是数组对象
  console.log(fields); // 无变化
} catch (err) {
  console.log(err);
}
```

  </TabItem>
  <TabItem value='Callback'>

```js {4}
conn.query(
  {
    sql: 'SELECT 1 AS `foo`, 2 AS `foo`',
    rowsAsArray: true,
  },
  function (err, results, fields) {
    console.log(results); // 在此查询中，结果将是数组数组，而不是对象数组
    console.log(fields); // 字段保持不变
  }
);
```

  </TabItem>
</Tabs>

<hr />

:::tip Getting Help
需要帮助吗？请在这里提问 [Stack Overflow](https://stackoverflow.com/questions/tagged/mysql2) 或 [GitHub](https://github.com/sidorares/node-mysql2/discussions).
如果您遇到问题，请 [在 GitHub 上提交 issues](https://github.com/sidorares/node-mysql2/issues).
:::

[npm-image]: https://img.shields.io/npm/v/mysql2.svg
[npm-url]: https://npmjs.org/package/mysql2
[node-version-image]: https://img.shields.io/node/v/mysql2.svg
[node-version-url]: https://nodejs.org/download/
[downloads-image]: https://img.shields.io/npm/dm/mysql2.svg
[downloads-url]: https://npmjs.org/package/mysql2
[license-url]: https://github.com/sidorares/node-mysql2/blob/master/License
[license-image]: https://img.shields.io/npm/l/mysql2.svg?maxAge=2592000
[node-mysql]: https://github.com/mysqljs/mysql
[coverage]: https://img.shields.io/codecov/c/github/sidorares/node-mysql2
[coverage-url]: https://app.codecov.io/github/sidorares/node-mysql2
[ci-url]: https://github.com/sidorares/node-mysql2/actions/workflows/ci-coverage.yml?query=branch%3Amaster
[ci-image]: https://img.shields.io/github/actions/workflow/status/sidorares/node-mysql2/ci-coverage.yml?event=push&style=flat&label=CI&branch=master
